/*
 * UMLSynch plugin for Eclipse
 * http://umlsynch.googlecode.com
 *
 * Copyright 2008-2010, Evgeny Alexeyev
 * Licensed under the EPL - v1.0
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */

package com.googlecode.umlsynch.EclipseDNDWrapper;

import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.core.model.CContainer;
import org.eclipse.cdt.internal.core.model.Enumeration;
import org.eclipse.cdt.internal.core.model.Namespace;
import org.eclipse.cdt.internal.core.model.Structure;
import org.eclipse.cdt.internal.core.model.TranslationUnit;
import org.eclipse.core.internal.resources.Project;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.CommonDragAdapter;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.part.EditorPart;

import com.googlecode.umlsynch.VPOperationServer.VPOperationServerCaller;
import com.googlecode.umlsynch.VPOperationServer.VPPoint;
import com.googlecode.umlsynch.VPOperationServer.VPSDEClassDescriptor;
import com.googlecode.umlsynch.VPOperationServer.VPSDEEnumDescriptor;
import com.googlecode.umlsynch.VPOperationServer.VPSDEPacketDescriptor;
import com.googlecode.umlsynch.VPOperationServer.VPWorkingAreaDescriptor;
import com.googlecode.umlsynch.eclipse.rpc.Debug.TEclipseDebug;

import org.eclipse.cdt.internal.ui.cview.CView;
import org.eclipse.cdt.internal.ui.cview.SelectionTransferDragAdapter;
import org.eclipse.cdt.internal.ui.dnd.CDTViewerDragAdapter;
import org.eclipse.cdt.internal.ui.dnd.FileTransferDragAdapter;
import org.eclipse.cdt.internal.ui.dnd.ResourceTransferDragAdapter;
import org.eclipse.cdt.internal.ui.dnd.TransferDragSourceListener;

import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;

public class EclipsePartListener implements IPartListener, ISelectionChangedListener {

	private TreePath CurrentSelectedPath = null;
	private Listener DragStartListener = null;
	private Listener DropStatusListener = null;
	private Listener DropErrorStatusListener = null;
	private String ProjectName;
	private String FileName;
	private String SelName;
	private String SelType;
	private String SelNamespace = "";
	
	TEclipseDebug debug = new TEclipseDebug("Part listener");
	
	private void PerformTransfer() {
        // Initialize presentation point		
		org.eclipse.swt.graphics.Point cursor = PlatformUI.getWorkbench().getDisplay().getCursorLocation();		
		VPPoint pt = new VPPoint();
		pt.X = cursor.x;
		pt.Y = cursor.y;
		
		VPWorkingAreaDescriptor wArea = VPOperationServerCaller.instance().GetWorkingArea();
		if (wArea.DiagramType.equals("ClassDiagram")) {
			if (SelType.equals("C_CLASS") || SelType.equals("C_STRUCT")) {
				VPSDEClassDescriptor desc = new VPSDEClassDescriptor();
				desc.className = SelNamespace + SelName;
				
				desc.projectName = ProjectName;
				desc.classFileName = FileName;
				
				VPOperationServerCaller.instance().CreateClassOnDiagram(desc, pt);
			}
		}
		if (wArea.DiagramType.equals("PackageDiagram")) {
			VPSDEPacketDescriptor desc = new VPSDEPacketDescriptor();
			
			if (SelType.equals("Project") || SelType.equals("TranslationUnit") 
					|| SelType.equals("CCONTAINER")) {
				desc.PacketName = SelName;
				desc.ProjectName = ProjectName;
				desc.PacketPath = FileName;
				VPOperationServerCaller.instance().CreatePacketOnDiagram(desc, pt);	
			}
		}
		if (wArea.DiagramType.equals("StateDiagram")) {
			if (SelType.equals("C_ENUM")) {
				VPSDEEnumDescriptor desc = new VPSDEEnumDescriptor();
				desc.FileName = FileName;
				desc.ProjectName = ProjectName;
				desc.EnumName = SelName;
				Enumeration mEnum = (Enumeration)CurrentSelectedPath.getLastSegment();
				ICElement[] treeChildren;
				try {
					treeChildren = mEnum.getChildren();
					desc.Fields = new String[treeChildren.length];
					for (int t=0; t < treeChildren.length; ++t) {
						String s = treeChildren[t].getElementName();
						desc.Fields[t] = treeChildren[t].getElementName();
					}
					VPOperationServerCaller.instance().CreateEnumOnDiagram(desc, pt);
				} catch (CModelException e) {
					System.out.println("CModelException on enum");
				}
				
			}			
		}
	}
	
	
	
	private void ParseCurrentPathInfo() {
		SelName = null;
		SelType = null;				
        int pathCount = CurrentSelectedPath.getSegmentCount();
		for (int i = 0; i < pathCount; ++i) {
			boolean isLastSegment = (pathCount == (i+1));
			
			if (CurrentSelectedPath.getSegment(i) instanceof Project) {
				Project prj = (Project)CurrentSelectedPath.getSegment(i);
				ProjectName = prj.getName();
				FileName = "";
				SelNamespace = "";
				if (isLastSegment) {
					SelName = ProjectName;
					SelType = "Project";				
				}
				continue;
			}
			if (CurrentSelectedPath.getSegment(i) instanceof TranslationUnit) {
				TranslationUnit tunit = (TranslationUnit)CurrentSelectedPath.getSegment(i);				
				
				if (isLastSegment) {
					SelName = tunit.getElementName();
					SelType = "TranslationUnit";				
				} else {
					FileName += tunit.getElementName();
				}
				continue;
			}
			if (CurrentSelectedPath.getSegment(i) instanceof Structure) {
				Structure mStruct = (Structure)CurrentSelectedPath.getSegment(i);
				if (isLastSegment) {
					SelName = mStruct.getElementName();
					SelType = mStruct.getTypeString();
				}
				continue;
			}
			if (CurrentSelectedPath.getSegment(i) instanceof Namespace) {
				Namespace mStruct = (Namespace)CurrentSelectedPath.getSegment(i);
				if (isLastSegment) {
					SelName = mStruct.getElementName();
					SelType = mStruct.getTypeString();
				}
				SelNamespace  = mStruct.getElementName() + "::";
				continue;
			}
			if (CurrentSelectedPath.getSegment(i) instanceof Enumeration) {
				Enumeration mEnum = (Enumeration)CurrentSelectedPath.getSegment(i);
				if (isLastSegment) {
				  SelName = mEnum.getElementName();
				  SelType = "C_ENUM";	
				}
				continue;
			}
			if (CurrentSelectedPath.getSegment(i) instanceof CContainer){
				CContainer mContainer = (CContainer)CurrentSelectedPath.getSegment(i);
				if (mContainer.getTypeString().equals("CCONTAINER")) {
					FileName += mContainer.getElementName() + "/";
				  if (isLastSegment) {
					  SelName = mContainer.getElementName();
					  SelType = "CCONTAINER";				
				  } 
				}
			}
		}
	}
	
	@Override
	public void partActivated(IWorkbenchPart part) {
		debug.Error("Activated " + part.getTitle());
		debug.Error("class sn - " + part.getClass().getSimpleName() );
		debug.Error("class cn - " + part.getClass().getCanonicalName());
		debug.Error("class n - " + part.getClass().getName() );

		if (part instanceof EditorPart) {
			EditorPart cue = (EditorPart)part;
		}
		
		if (part.getClass().getSimpleName().equals("ClassDiagramEditor")) {
			if (part.getSite() != null) {
				debug.Error("Site is not null" );		
			}
			part.addPropertyListener(new IPropertyListener() {

				@Override
				public void propertyChanged(Object source, int propId) {
					debug.Error("ClassDiagramEditor propchanged:" + propId);
					if (source != null) {
					   debug.Error("ClassDiagramEditor" + source.getClass().getSimpleName());
					} 
					
				}});
		}
		
		if ((part instanceof CView) && (part.getTitle().equals("C/C++ Projects"))) {
			CView tPart = (CView)part;
			Transfer[] types = new Transfer[] { GadgetTransfer.getInstance() };
			
			DragSource ds = (DragSource)tPart.getViewer().getControl().getData(DND.DRAG_SOURCE_KEY);
			if (ds != null) {
				int ops= DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
				Listener[] lnrs0 = tPart.getViewer().getControl().getListeners(ops);
				Listener[] lnrs = ds.getListeners(DND.DragStart);
				if (lnrs != null)
				  ds.removeListener(DND.DragStart, lnrs[0]);
	            TransferDragSourceListener[] dragListeners= new TransferDragSourceListener[] {
                        new SelectionTransferDragAdapter(tPart.getViewer()),
                        new ResourceTransferDragAdapter(tPart.getViewer()),
                        new FileTransferDragAdapter(tPart.getViewer()),
                        new TransferDragSourceListener() {

							@Override
							public Transfer getTransfer() {
								return GadgetTransfer.getInstance();
							}

							@Override
							public void dragFinished(DragSourceEvent event) {
								// TODO Auto-generated method stub
								
							}

							@Override
							public void dragSetData(DragSourceEvent event) {
								// TODO Auto-generated method stub
								
							}

							@Override
							public void dragStart(DragSourceEvent event) {
								event.doit = true;								
							}}
	            };
	            
                ds.addDragListener(new CDTViewerDragAdapter(tPart.getViewer(), dragListeners));
				
				
				int style1 = ds.getStyle();
				Control ctl = ds.getControl();
				Transfer[] types1 = ds.getTransfer();
				Transfer[] types2 = new Transfer[types1.length + 1];
				for (int t=0; t<types1.length; ++t) {
					types2[t+1] = types1[t];
				}
				types2[0] = types[0];
				ds.setTransfer(types2);
				ds.addDragListener(new DragSourceListener() {

				@Override
				public void dragFinished(DragSourceEvent event) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void dragSetData(DragSourceEvent event) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void dragStart(DragSourceEvent event) {
					debug.Error("Drag Started for PE 2");
					
				}});
			}
		}
		
		if ((part instanceof CommonNavigator)  && (part.getTitle().equals("Project Explorer"))) {			
			CommonNavigator tPart = (CommonNavigator)part;
			tPart.getCommonViewer().addSelectionChangedListener(this);
			Transfer[] types0 = new Transfer[] { GadgetTransfer.getInstance() };

			try {

				Control ctl = tPart.getCommonViewer().getControl();

				DragSource ds = (DragSource)tPart.getCommonViewer().getControl().getData(DND.DRAG_SOURCE_KEY);
				if (ds != null) {
					Transfer[] types1 = ds.getTransfer();
					Transfer[] types2 = new Transfer[types1.length + 1];
					types2[0] = types0[0];
					for (int t=0; t<types1.length; ++t) {
						types2[t+1] = types1[t];
					}
					ds.setTransfer(types2);
					ds.addDragListener(new DragSourceListener() {

						@Override
						public void dragFinished(DragSourceEvent event) {
							// TODO Auto-generated method stub

						}

						@Override
						public void dragSetData(DragSourceEvent event) {
							// TODO Auto-generated method stub

						}

						@Override
						public void dragStart(DragSourceEvent event) {
							debug.Error("Drag Started for PE");
							event.doit = true;

						}});
				}
			} catch (SWTError ex) {
				System.out.println("Drag Started for PE" + ex.toString());
			} finally {
				System.out.println("Drag Started for PE");
			}
		}
	}

	@Override
	public void partBroughtToTop(IWorkbenchPart part) {
	}

	@Override
	public void partClosed(IWorkbenchPart part) {
	}

	@Override
	public void partDeactivated(IWorkbenchPart part) {
		if ((part instanceof CommonNavigator) && (part.getTitle().equals("Project1 Explorer"))) {			
			CommonNavigator tPart = (CommonNavigator)part;
			tPart.getCommonViewer().removeSelectionChangedListener(this);
			PlatformUI.getWorkbench().getDisplay().removeFilter(DND.DragStart, DragStartListener);			
		}
	}

	@Override
	public void partOpened(IWorkbenchPart part) {
	}

	@Override
	public void selectionChanged(SelectionChangedEvent event) {
		TreeSelection sel = (TreeSelection)event.getSelection();
		CurrentSelectedPath = null;
		if (sel != null) {
			TreePath[] paths = sel.getPaths();
			CurrentSelectedPath = ((paths != null) && (paths.length > 0)) ? paths[0] : null;
		} 
	}
	
}
